using UnityEngine;
using System.Collections;
using System.Collections.Generic;

/**
 * Helper class for GUIs that contain items
 * e.g. inventory, shops, etc.
 */
public class ItemContainerGui {
	/* These values are specified and uniquely determine the shape */
	public readonly float box_side_length;
	public readonly float left_box_spacing;
	public readonly float right_box_spacing;
	public readonly float top_box_spacing;
	public readonly float bottom_box_spacing;
	public readonly float top_border;
	public readonly float left_border;
	public readonly float right_border;
	public readonly float bottom_border;
	
	/**
	 * Maybe better to have public getters and private setters but meh
	 * 
	 * IMPORTANT: top_left is the offset from the top_left of the GUI window
	 * It is NOT the top_left in relation to absolute GUI coords
	 */
	public Vector2 top_left;
	public readonly int num_rows;
	public readonly int num_columns;
	
	/* These are derived from above values */
	public readonly float height;
	public readonly float width;
	
	public ItemContainerGui(
		Vector2 top_left,
		int num_rows,
		int num_columns,
		float box_side_length=32,
		float left_box_spacing=2,
		float right_box_spacing=2,
		float top_box_spacing=2,
		float bottom_box_spacing=2,
		float top_border=15,
		float left_border=1,
		float right_border=1,
		float bottom_border=5) {
		
		this.top_left = top_left;
		this.num_rows = num_rows;
		this.num_columns = num_columns;
		
		this.box_side_length = box_side_length;
		this.left_box_spacing = left_box_spacing;
		this.right_box_spacing = right_box_spacing;
		this.top_box_spacing = top_box_spacing;
		this.bottom_box_spacing = bottom_box_spacing;
		this.top_border = top_border;
		this.left_border = left_border;
		this.right_border = right_border;
		this.bottom_border = bottom_border;
		
		this.height = this.top_border +
			(this.num_rows * this.box_side_length) + 
			(this.num_rows * this.top_box_spacing) +
			(this.num_rows * this.bottom_box_spacing) +
			this.bottom_border;
		
		this.width = this.left_border +
			(this.num_columns * this.box_side_length) +
			(this.num_columns * this.left_box_spacing) + 
			(this.num_columns * this.right_box_spacing) + 
			this.right_border;
	}
	
	/**
	 * @param row, column: both are 0-indexed
	 * @returns Rect that corresponds to the box...note that it is a GUI rect
	 * which means it's relative to the top_left of the GUI
	 * i.e. top left of the window is (0,0)
	 */
	public Rect GetBoxRect(int row, int column) {
		/* Maybe should memoize this, but meh */
		return new Rect(
			this.top_left.x + this.left_border +
				(column *
					(this.left_box_spacing + this.box_side_length + this.right_box_spacing)) +
				this.left_box_spacing,
			this.top_left.y + this.top_border +
				(row *
					(this.top_box_spacing + this.box_side_length + this.bottom_box_spacing)) +
				this.top_box_spacing,
			this.box_side_length,
			this.box_side_length);
	}
	
	public Rect GetBoxRect(Pair<int, int> row_and_column) {
		return this.GetBoxRect(row_and_column.Item1, row_and_column.Item2);
	}
	
	public ItemStack GetBoxItemContainer(int row, int column) {
		return null;
	}
	
	/**
	 * @param x, y: this should be in GUI space (i.e. top left of GUI is (0,0))
	 * @param box: if found, will be the tuple (row, column)
	 * @returns: true if found, false otherwise
	 */
	public bool GetBoxFromPos(float x, float y, out Pair<int, int> box) {
		float dist;
		float dim_size;
		float edge;
		int column;
		int row;
		
		/* compiler forces you to assign to box meh */
		box.Item1 = 0;
		box.Item2 = 0;
		
		if ((x < this.top_left.x + this.left_border) ||
			(x > this.top_left.x + this.width - this.right_border) ||
			(y < this.top_left.y + this.top_border) ||
			(y > this.top_left.y + this.height - this.bottom_border)) {
			return false;
		}
		
		/**
		 * TODO: need to draw this, but basically use integer truncation to find the left edge
		 * of the column it's in
		 * Then see if it's in the first part (box) or the second part (spacing)
		 */
		dist = x - (this.top_left.x + this.left_border);
		dim_size = this.left_box_spacing + this.box_side_length + this.right_box_spacing;
		column = (int)(dist / dim_size);
		edge = this.top_left.x + this.left_border + (dim_size * column) + this.left_box_spacing;
		if (x - edge > this.box_side_length) {
			return false;
		}
		
		dist = y - (this.top_left.y + this.top_border);
		dim_size = this.top_box_spacing + this.box_side_length + this.bottom_box_spacing;
		row = (int)(dist / dim_size);
		edge = this.top_left.y + this.top_border + (dim_size * row) + this.top_box_spacing;
		if (y - edge > this.box_side_length) {
			return false;
		}
		
		box.Item1 = row;
		box.Item2 = column;
		return true;
	}
	
	public bool GetBoxFromPos(Vector2 pos, out Pair<int, int> box) {
		return this.GetBoxFromPos(pos.x, pos.y, out box);
	}
	
	public bool GetBoxFromPos(Vector2 pos, out int row, out int col) {
		Pair<int, int> box;
		bool ret;
		
		ret = this.GetBoxFromPos(pos.x, pos.y, out box);
		
		row = box.Item1;
		col = box.Item2;
		
		return ret;
	}
}
